
#import "RNXG.h"
#import "XGPush.h"

static NSString* const RNXG_ON_REGISTER = @"RNXG_ON_REGISTER";
static NSString* const RNXG_ON_UNREGISTER = @"RNXG_ON_UNREGISTER";
static NSString* const RNXG_NOTIFICATION_ON_RECEIVE = @"RNXG_NOTIFICATION_ON_RECEIVE";
static NSString* const RNXG_NOTIFICATION_ON_CLICK = @"RNXG_NOTIFICATION_ON_CLICK";

static NSString* const RNXG_NOTIFICATION_DATA_KEY = @"custom";
static NSString* const RNXG_NOTIFICATION_CACHE_DATA_KEY = @"rnxg";

@interface RNXG()<XGPushDelegate> {
    uint32_t _accessID;
    BOOL _isReactDidLoad;
    NSDictionary* _launchAppNotification;
    NSMutableDictionary* _cachedNotifications;
}

@property (nonatomic,strong) NSString * accessKey;
//@property (nonatomic,strong) NSString * accessID;
@property (nonatomic,strong) XGPush * xgpush;

@end

@implementation RNXG

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

+ (BOOL) requiresMainQueueSetup {
    return YES;
}

RCT_EXPORT_MODULE()

PSSSingletonM(Instance,RNXG);

- (instancetype) init {
    static id _instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (_instance = [super init]) {
            _xgpush = [XGPush defaultManager];
            NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
            [defaultCenter removeObserver:self];

            [defaultCenter addObserver:self
                              selector:@selector(reactJSDidload)
                                  name:RCTJavaScriptDidLoadNotification
                                object:nil];
        }
    });
    
    return _instance;
}

- (void)dealloc{
    _accessID = nil;
    _accessKey = nil;
    _xgpush = nil;
    _launchAppNotification = nil;
}

- (void)reactJSDidload {
    _isReactDidLoad = YES;
}

- (void)enableDebug:(BOOL)enabled
{
    _xgpush.enableDebug = enabled;
}

- (void) setAppID:(NSString*)appID {
    _accessID = [[NSNumberFormatter new] numberFromString:appID].unsignedIntValue;
}

- (void)setCredential:(NSString*)appID :(NSString*)accessKey {
    [self setAppID:appID];
    _accessKey = accessKey;
}

-(void)registerPush {
    [_xgpush startXGWithAppID:_accessID
                       appKey:_accessKey
                     delegate:self];
}

-(void)unregisterPush {
    [_xgpush stopXGNotification];
}

RCT_EXPORT_METHOD(enableDebug:(BOOL)enabled
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    [self enableDebug: enabled];
    resolve(nil);
}

RCT_EXPORT_METHOD(setAccessId:(NSString*)appID
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    [self setAppID:appID];
    resolve(nil);
}

RCT_EXPORT_METHOD(setAccessKey:(NSString*)accessKey
            resolver:(RCTPromiseResolveBlock)resolve
            rejecter:(RCTPromiseRejectBlock)reject)
{
    _accessKey = accessKey;
    resolve(nil);
}

RCT_EXPORT_METHOD(getToken:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    NSString* token = [XGPushTokenManager defaultTokenManager].deviceTokenString;
    resolve(token);
}

RCT_EXPORT_METHOD(registerPush:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    [self registerPush];
    resolve(nil);
}

RCT_EXPORT_METHOD(unregisterPush:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    [self unregisterPush];
    resolve(nil);
}

RCT_EXPORT_METHOD(removeDeliveredNotifications:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center removeAllDeliveredNotifications];
    resolve(nil);
}

RCT_EXPORT_METHOD(getLaunchAppNotification:(RCTPromiseResolveBlock)resolve
            rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve(_launchAppNotification);
}

/*Returns a list of all notification requests that are scheduled and waiting to be delivered. 取得的应该是定时本地推送*/
/*RCT_EXPORT_METHOD(getPendingNotifications:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) {
        NSMutableArray *array = [NSMutableArray array];
        for (UNNotificationRequest *request in requests) {
            [array addObject:request.content.userInfo];
        }
        resolve(array);
    }];
}*/

/* 取得在app没启动时，在通知中心中的推送，一旦清除，就再也取不到了。应用在后台时收到推送，如果不点击不清除，调用此方法也会包含该推送。 */
/*RCT_EXPORT_METHOD(getDeliveredNotifications:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
        NSMutableArray *array = [NSMutableArray array];
        for (UNNotification *notification in notifications) {
            [array addObject:notification.request.content.userInfo];
        }
        resolve(array);
    }];
}*/

RCT_EXPORT_METHOD(popDeliveredNotifications:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
        NSMutableArray *array = [NSMutableArray array];
        for (UNNotification *notification in notifications) {
            [array addObject:notification.request.content.userInfo];
        }
        
        [center removeAllDeliveredNotifications];
        [_xgpush setXgApplicationBadgeNumber:0];
        [[XGPush defaultManager] setBadge:0];
        resolve(array);
    }];
}

RCT_EXPORT_METHOD(popCachedNotifications:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    NSArray * array = [self getCachedNotifications];
    [self removeAllCachedNotifications];
    resolve(array);
}

- (NSUserDefaults*) getUserDefaults {
    return [NSUserDefaults standardUserDefaults];
}

- (NSArray*) getCachedNotifications {
    NSUserDefaults *defaults = [self getUserDefaults];
    NSDictionary *cachedNotifications = [defaults dictionaryForKey:RNXG_NOTIFICATION_CACHE_DATA_KEY];
    NSMutableArray *array = [NSMutableArray array];
    for (NSDictionary *notification in [cachedNotifications allValues]) {
        [array addObject:notification];
    }
    return array;
}

- (void) removeAllCachedNotifications {
    [[self getUserDefaults] removeObjectForKey:RNXG_NOTIFICATION_CACHE_DATA_KEY];
    [[self getUserDefaults] synchronize];
}

- (void) cacheNotification:(NSDictionary *)notification
{
    NSUserDefaults *defaults = [self getUserDefaults];
    if(nil == _cachedNotifications){
        _cachedNotifications = [NSMutableDictionary new];
    }
    NSString* key = [[NSUUID UUID] UUIDString];//notification[@"xg"][@"msgid"]

    [_cachedNotifications setObject:notification forKey:key];
    
    [defaults setObject:_cachedNotifications forKey:RNXG_NOTIFICATION_CACHE_DATA_KEY];
    [defaults synchronize];
}

- (NSDictionary<NSString *, NSString *> *) constantsToExport {
    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                          RNXG_ON_REGISTER,RNXG_ON_REGISTER,
                          RNXG_ON_UNREGISTER,RNXG_ON_UNREGISTER,
                          RNXG_NOTIFICATION_ON_CLICK,RNXG_NOTIFICATION_ON_CLICK,
                          RNXG_NOTIFICATION_ON_RECEIVE,RNXG_NOTIFICATION_ON_RECEIVE,
                          /*RNXG_NOTIFICATION_ON_SHOW,RNXG_NOTIFICATION_ON_SHOW,*/
                          nil];
    return dict;
}

- (NSArray<NSString *> *) supportedEvents {
    return @[RNXG_ON_REGISTER,RNXG_ON_UNREGISTER,RNXG_NOTIFICATION_ON_CLICK,RNXG_NOTIFICATION_ON_RECEIVE/*,RNXG_NOTIFICATION_ON_SHOW*/];
}

- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
        UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];

        [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge)
                              completionHandler:^(BOOL granted, NSError * _Nullable error) {
                                  // Enable or disable features based on authorization.
                                  if (granted) {
                                      dispatch_async(dispatch_get_main_queue(), ^{
                                          [application registerForRemoteNotifications];
                                      });
                                  }
                              }];
#endif
    }
    else { // > 8.0
        UIUserNotificationType myTypes = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;

        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:myTypes categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    }
//    [[XGPush defaultManager] setEnableDebug:false];
    [_xgpush setXgApplicationBadgeNumber:0];//应用角标清零
    [[XGPush defaultManager] setBadge:0];//上报角标，配合角标自动+1功能
    [_xgpush reportXGNotificationInfo:launchOptions];//上报统计信息

    /*if(launchOptions) {//通过点击推送唤起的应用，信鸽会正常调用app在后台时收到推送的方法，故所以此处不用处理。
        NSDictionary* remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

        if(remoteNotification) {

            NSLog(@"推送过来的消息是%@", remoteNotification);
        }
    }*/
}
/*应用在后台时收到推送，或者直接通过xcode安装应用，但是没点击应用图标时也会收到后台推送，应用在任务管理器中被移除，无法进行调试*/
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
//    if(UIApplicationStateActive != [UIApplication sharedApplication].applicationState){
    if(_isReactDidLoad){
//        if(UIApplicationStateActive != application.applicationState){
            [self receivedRemoteNotification:userInfo];
//        }
    }else{
//        if(UIApplicationStateActive != application.applicationState){
            [self cacheNotification:userInfo];
            //NSLog(@"receive notification when app is not launched: %@", userInfo);
//        }
    }
    
    completionHandler(UIBackgroundFetchResultNewData);
}



- (void) receivedRemoteNotification:(NSDictionary *)data{
//    [self sendEventWithName:RNXG_NOTIFICATION_ON_RECEIVE body:data[RNXG_NOTIFICATION_DATA_KEY]];
    [self sendEventWithName:RNXG_NOTIFICATION_ON_RECEIVE body:data];
    [_xgpush reportXGNotificationInfo:data];
}

#pragma mark - XGPushDelegate
//@optional
//应用在前台时收到推送 或 在后台时收到静默通知
/*- (void)xgPushDidReceiveRemoteNotification:(nonnull id)notification withCompletionHandler:(nullable void (^)(NSUInteger))completionHandler{
    UNNotification * response = notification;

    UIApplicationState state = [UIApplication sharedApplication].applicationState;
    if (UIApplicationStateActive != state) { //应用在后台收到了推送
        
        completionHandler(UIBackgroundFetchResultNewData);
//        completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
    } else { //应用在前台收到推送，也显示推送通知
        [self receivedRemoteNotification:response.request.content.userInfo];
        completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
    }
}*/

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 //当前sdk版本 > 10.0
// App 在前台弹通知需要调用这个接口（xgPushDidReceiveRemoteNotification方法存在时，优先调用该方法，此方法会被覆盖）
- (void)xgPushUserNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
    [self receivedRemoteNotification:notification.request.content.userInfo];
    [_xgpush setXgApplicationBadgeNumber:0];//应用角标清零
    [[XGPush defaultManager] setBadge:0];//上报角标，配合角标自动+1功能
    completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
}

//应用不在前台时点击推送 或 未启动时点击推送启动应用 或 应用在前台点击了推送
- (void)xgPushUserNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    UIApplicationState state = [UIApplication sharedApplication].applicationState;

    NSDictionary* data = response.notification.request.content.userInfo;
    if (UIApplicationStateActive == state){ //应用在前台点击了推送
//        [self sendEventWithName:RNXG_NOTIFICATION_ON_CLICK body:data[RNXG_NOTIFICATION_DATA_KEY]];
        [self sendEventWithName:RNXG_NOTIFICATION_ON_CLICK body:data];
    }else /*if (UIApplicationStateInactive != state)*/ {//未启动时点击推送启动应用 或 不在前台的时候点击推送
        if(_isReactDidLoad) {// background时点击推送
//            [self sendEventWithName:RNXG_NOTIFICATION_ON_CLICK body:data[RNXG_NOTIFICATION_DATA_KEY]];
            [self sendEventWithName:RNXG_NOTIFICATION_ON_CLICK body:data];
        }else{
            //保存最新一次的推送消息，供js获取
            _launchAppNotification = data;
        }
    }

    [[XGPush defaultManager] reportXGNotificationResponse:response];
    completionHandler();
}
#endif

- (void)xgPushDidFinishStart:(BOOL)isSuccess error:(nullable NSError *)error {
//    NSDictionary *dic = [NSDictionary dictionary];
    NSString *deviceToken = [[XGPushTokenManager defaultTokenManager] deviceTokenString];
//    if(deviceToken){
//        [dic setValue:deviceToken forKey:@"token"];
//    }
    /*if(isSuccess){
        [self sendEventWithName:RNXG_ON_REGISTER body:deviceToken];
    }*/
    if(_isReactDidLoad) {
        [self sendEventWithName:RNXG_ON_REGISTER body:@{@"isSuccess":[NSNumber numberWithBool: isSuccess],@"token":deviceToken,@"errCode":[NSNumber numberWithInteger:error.code],@"msg":error.userInfo}];
    }
}

- (void)xgPushDidFinishStop:(BOOL)isSuccess error:(nullable NSError *)error{
    /*if(isSuccess){
        [self sendEventWithName:RNXG_ON_UNREGISTER body:[NSNumber numberWithInteger:error.code]];
    }*/
    [self sendEventWithName:RNXG_ON_UNREGISTER body:@{@"isSuccess":[NSNumber numberWithBool: isSuccess],@"errCode":[NSNumber numberWithInteger:error.code],@"msg":error.userInfo}];
}

/*- (void)xgPushDidReportNotification:(BOOL)isSuccess error:(nullable NSError *)error{

}

- (void)xgPushDidSetBadge:(BOOL)isSuccess error:(nullable NSError *)error{

}

- (void)xgPushDidRegisteredDeviceToken:(nullable NSString *)deviceToken error:(nullable NSError *)error{
//    [self sendEventWithName:@"registerdevicetokenresult" body:[NSDictionary dictionaryWithObjectsAndKeys:deviceToken,@"deviceToken",error,@"error", nil]];
}*/

@end
  
